package model;

import org.mybeans.dao.DAOException;
import org.mybeans.factory.BeanFactory;
import org.mybeans.factory.BeanFactoryException;
import org.mybeans.factory.BeanTable;
import org.mybeans.factory.DuplicateKeyException;
import org.mybeans.factory.MatchArg;
import org.mybeans.factory.RollbackException;
import org.mybeans.factory.Transaction;

import databeans.Entity;
import interfas.EntityInterface;

public class EntityDAO implements EntityInterface {

	private BeanFactory<Entity> factory;
	private int eid = 1;
	
	public EntityDAO() throws DAOException {
		try {
			BeanTable<Entity> table = BeanTable.getInstance(Entity.class, "entity");
			if (!table.exists())
				table.create("eid");
			
			table.setIdleConnectionCleanup(true);
			factory = table.getFactory();
			
			if (factory.getBeanCount() > 0)
				eid = factory.match(MatchArg.max("eid"))[0].getEid() + 1;
			
		} catch (BeanFactoryException e) {
			throw new DAOException(e);
		} catch (RollbackException e) {
			throw new DAOException(e);
		}
	}
	
	public void create(Entity e, EntityClassDAO ecDAO) throws DAOException {
		try {
			// Check for foreign key constraint
			if (ecDAO.lookup(e.getEcid()) == null) {
				throw new DAOException("ecid must exist in entityclass table");
			}
			
			Transaction.begin();
			Entity dbe = factory.create(e.getEid());
			factory.copyInto(e, dbe);
			eid++;
			Transaction.commit();
		} catch (DuplicateKeyException ex) {
			throw new DAOException("An entity with eid " + e.getEid() + " already exists");
		} catch (RollbackException ex) {
			throw new DAOException(ex);
		} finally {
			if (Transaction.isActive())
				Transaction.rollback();
		}
	}

	public Entity lookup(int eid) throws DAOException {
		try {
			return factory.lookup(eid);
		} catch (RollbackException e) {
			throw new DAOException(e);
		}
	}

	public Entity[] getEntityByEcid(int ecid) throws DAOException {
		try {
			return factory.match(MatchArg.equals("ecid", ecid));
		} catch (RollbackException e) {
			throw new DAOException(e);
		}
	}
	
	public Entity[] getEntityByName(String name) throws DAOException {
		try {
			return factory.match(MatchArg.equals("name", name));
		} catch (RollbackException e) {
			throw new DAOException(e);
		}
	}
	
	//Gets an entity by ecid and name. An (ecid,name) tuple should be unique.
	public Entity getEntityByEcidName(int ecid, String name) throws DAOException {
		try {
			Entity[] en = factory.match(MatchArg.equals("ecid", ecid), MatchArg.equals("name", name));
			if (en.length != 1)
				throw new RollbackException("Theres more than one entity!");
			return en[0];
		} catch (RollbackException e) {
			throw new DAOException(e);
		}
	}
	
	public void delete(int eid) throws DAOException {
		try {
			Transaction.begin();
			Entity dbEntity = lookup(eid);
			if (dbEntity == null)
				throw new DAOException("Entity with eid " + eid + " doesn't exist");
			factory.delete(eid);
			Transaction.commit();
		} catch (RollbackException e) {
			throw new DAOException(e);
		} finally {
			if (Transaction.isActive())
				Transaction.rollback();
		}
	}

	public int size() throws DAOException {
		try {
			return factory.getBeanCount();
		} catch (RollbackException e) {
			throw new DAOException(e);
		}
	}
	
	//Gets the number of entities by ecid.
	public int sizeByEcid(int ecid) throws DAOException {
		return getEntityByEcid(ecid).length;
	}
	
	public int getEid() {
		return eid;
	}
}
